﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using System.Timers;

enum Shape { rectange, burst, inward };
enum D3DBLEND {
  D3DBLEND_ZERO              = 1,
  D3DBLEND_ONE               = 2,
  D3DBLEND_SRCCOLOR          = 3,
  D3DBLEND_INVSRCCOLOR       = 4,
  D3DBLEND_SRCALPHA          = 5,
  D3DBLEND_INVSRCALPHA       = 6,
  D3DBLEND_DESTALPHA         = 7,
  D3DBLEND_INVDESTALPHA      = 8,
  D3DBLEND_DESTCOLOR         = 9,
  D3DBLEND_INVDESTCOLOR      = 10,
  D3DBLEND_SRCALPHASAT       = 11,
  D3DBLEND_BOTHSRCALPHA      = 12,
  D3DBLEND_BOTHINVSRCALPHA   = 13,
  D3DBLEND_BLENDFACTOR       = 14,
  D3DBLEND_INVBLENDFACTOR    = 15,
  D3DBLEND_SRCCOLOR2         = 16,
  D3DBLEND_INVSRCCOLOR2      = 17,
};

public struct Particles
{
    public float LifeTime;
    public float CurrentLife;
    public float Rotation;
    public float Scale;
    public Vector2 Velocity;
    public Vector2 CurrentPosition;
    public Vector2 StartPosition;
    public Color CurrentColor;
    public bool IsAlive;
};

namespace DigitalHydraParticleEditor
{
    class Emitter
    {
        private Rectangle rect;

        public Rectangle Rect
        {
            get { return rect; }
            set { rect = value; }
        }

        public void SetRectWidth(int width)
        {
            this.rect.Width = width;
        }

        public void SetRectHeight(int height)
        {
            this.rect.Height = height;
        }

        public void SetRectX(int X)
        {
            this.rect.X += X;
        }

        public void SetRectY(int Y)
        {
            this.rect.Y += Y;
        }

        private bool islooping;

        public bool Islooping
        {
            get { return islooping; }
            set { islooping = value; }
        }

        private Particles[] particles;

        public Particles[] Particles
        {
            get { return particles; }
            set { particles = value; }
        }

        private int SourceBlend;

        public int SourceBlend1
        {
            get { return SourceBlend; }
            set { SourceBlend = value; }
        }

        private int DestinationBlend;

        public int DestinationBlend1
        {
            get { return DestinationBlend; }
            set { DestinationBlend = value; }
        }

        private int MaxParticles;

        public int MaxParticles1
        {
            get { return MaxParticles; }
            set { MaxParticles = value; }
        }

        private string ImageFileName;

        public string ImageFileName1
        {
            get { return ImageFileName; }
            set { ImageFileName = value; }
        }

        private int ImageID;

        public int ImageID1
        {
            get { return ImageID; }
            set { ImageID = value; }
        }

        private Vector2 Gravity;

        public Vector2 Gravity1
        {
            get { return Gravity; }
            set { Gravity = value; }
        }

        private Vector2 Velocity1;

        public Vector2 Velocity11
        {
            get { return Velocity1; }
            set { Velocity1 = value; }
        }

        private Vector2 Velocity2;

        public Vector2 Velocity21
        {
            get { return Velocity2; }
            set { Velocity2 = value; }
        }

        private Color StartColor;

        public Color StartColor1
        {
            get { return StartColor; }
            set { StartColor = value; }
        }
        private Color EndColor;

        public Color EndColor1
        {
            get { return EndColor; }
            set { EndColor = value; }
        }
        private float StartScale;

        public float StartScale1
        {
            get { return StartScale; }
            set { StartScale = value; }
        }

        private float EndScale;

        public float EndScale1
        {
            get { return EndScale; }
            set { EndScale = value; }
        }

        private float Rotation;

        public float Rotation1
        {
            get { return Rotation; }
            set { Rotation = value; }
        }
        private float minLifeSpan;

        public float MinLifeSpan1
        {
            get { return minLifeSpan; }
            set { minLifeSpan = value; }
        }

        private float maxLifeSpan;

        public float MaxLifeSpan
        {
            get { return maxLifeSpan; }
            set { maxLifeSpan = value; }
        }

        private Vector2 Offset;

        public Vector2 Offset1
        {
            get { return Offset; }
            set { Offset = value; }
        }

        public float ToRadians(float degrees)
        {
            return ((degrees) * (3.141592654f / 180.0f));
        }

        public float ToDegrees(float radians)
        {
            return ((radians) * (180.0f / 3.141592654f));
        }

        private int StartAlpha;

        public int StartAlpha1
        {
            get { return StartAlpha; }
            set { StartAlpha = value; }
        }

        private int EndAlpha;

        public int EndAlpha1
        {
            get { return EndAlpha; }
            set { EndAlpha = value; }
        }

        public Emitter(){}

        public Emitter(int width, int height, int X, int Y,int MaxParticles,
            int minLife,int maxLife,float startscale, float endscale, 
            float VelX1, float VelX2, float VelY1, float VelY2, float Rotation, 
            string Filename, int SAlpha, int EAlpha)
        {
            this.rect.Width = width;
            this.rect.Height = height;
            this.rect.X = X;
            this.rect.Y = Y;
            this.MaxParticles = MaxParticles;
            this.particles = new Particles[this.MaxParticles];
            this.ImageFileName = Filename;
            this.SourceBlend = (int)D3DBLEND.D3DBLEND_SRCALPHA;
            this.DestinationBlend = (int)D3DBLEND.D3DBLEND_INVSRCALPHA;
            this.islooping = true;
            this.StartAlpha = SAlpha;
            this.StartColor = Color.FromArgb(this.StartAlpha, Color.Blue);
            this.EndAlpha = EAlpha;
            this.EndColor = Color.FromArgb(this.EndAlpha,Color.White);
            this.StartScale = startscale;
            this.Rotation = Rotation;
            this.Velocity1.X = VelX1;
            this.Velocity1.Y = VelY1;
            this.Velocity2.X = VelX2;
            this.Velocity2.Y = VelY2;
            this.minLifeSpan = minLife;
            this.maxLifeSpan = maxLife;
            this.ImageID = SGP.ManagedTextureManager.Instance.LoadTexture(ImageFileName, 0);
            this.Offset.X = SGP.ManagedTextureManager.Instance.GetTextureWidth(ImageID) >> 1;
            this.Offset.Y = SGP.ManagedTextureManager.Instance.GetTextureHeight(ImageID) >> 1;
            Random rand = new Random();

            for (int i = 0; i < this.MaxParticles; i++)
            {
                particles[i] = new Particles();
                particles[i].LifeTime = rand.Next((int)this.minLifeSpan, (int)this.maxLifeSpan);
                particles[i].CurrentLife = 0;
                particles[i].Scale = this.StartScale;
                particles[i].Velocity.X = rand.Next((int)this.Velocity2.X,(int)this.Velocity1.X);
                particles[i].Velocity.Y = rand.Next((int)this.Velocity2.Y, (int)this.Velocity1.Y);
                particles[i].StartPosition.X = rand.Next(rect.Left,rect.Right);
                particles[i].StartPosition.Y = rand.Next(rect.Top, rect.Bottom);
                particles[i].CurrentPosition = particles[i].StartPosition;
                particles[i].CurrentColor = this.StartColor;
                particles[i].IsAlive = true;
            }
        }

        public void Update(double ElapsedTime,int width, int height, int X, int Y,int MaxParticles,
            int minLife, int maxLife, float startscale, float endscale, 
            float VelX1, float VelX2, float VelY1, float VelY2,float rotation,
            float GravityX, float GravityY, int Source, int Dest, bool isloop,
            int SAlpha, int EAlpha)
        {
            this.rect.Width = width;
            this.rect.Height = height;
            this.rect.X = X;
            this.rect.Y = Y;
            this.minLifeSpan = minLife;
            this.maxLifeSpan = maxLife;
            this.StartScale = startscale;
            this.EndScale = endscale;
            this.Velocity1.X = VelX1;
            this.Velocity1.Y = VelY1;
            this.Velocity2.X = VelX2;
            this.Velocity2.Y = VelY2;
            this.Rotation = rotation;
            this.Gravity.X = GravityX;
            this.Gravity.Y = GravityY;
            this.SourceBlend = Source;
            this.DestinationBlend = Dest;
            this.islooping = isloop;
            this.StartAlpha = SAlpha;
            this.StartColor = Color.FromArgb(this.StartAlpha, this.StartColor);
            this.EndAlpha = EAlpha;
            this.EndColor = Color.FromArgb(this.EndAlpha, EndColor);
            this.Offset.X = SGP.ManagedTextureManager.Instance.GetTextureWidth(ImageID) >> 1;
            this.Offset.Y = SGP.ManagedTextureManager.Instance.GetTextureHeight(ImageID) >> 1;
            Random rand = new Random();

            for (int i = 0; i < this.MaxParticles; i++)
            {
                particles[i].CurrentLife += (float)ElapsedTime;
                
                if(this.StartScale < this.EndScale)
                    particles[i].Scale += this.StartScale * (float)ElapsedTime;
                else if(this.StartScale > this.EndScale)
                    particles[i].Scale -= this.StartScale * (float)ElapsedTime;

                particles[i].Rotation += this.Rotation;
                particles[i].CurrentPosition.X += particles[i].Velocity.X * (float)ElapsedTime;
                particles[i].CurrentPosition.X += this.Gravity.X;
                particles[i].CurrentPosition.Y += particles[i].Velocity.Y * (float)ElapsedTime;
                particles[i].CurrentPosition.Y += this.Gravity.Y;
                particles[i].CurrentColor = ColorOperator.Lerp(this.StartColor, this.EndColor, particles[i].CurrentLife);

                if (particles[i].CurrentLife > particles[i].LifeTime && islooping == true)
                {
                    particles[i].LifeTime = (float)(rand.Next((int)(this.minLifeSpan*1000), (int)(this.maxLifeSpan * 1000))) / 1000.0f;
                    particles[i].CurrentLife = 0;
                    particles[i].Scale = this.StartScale;
                    particles[i].Rotation = this.Rotation;
                    particles[i].Velocity.X = rand.Next((int)this.Velocity2.X, (int)this.Velocity1.X);
                    particles[i].Velocity.Y = rand.Next((int)this.Velocity2.Y, (int)this.Velocity1.Y);
                    particles[i].StartPosition.X = rand.Next(rect.Left, rect.Right);
                    particles[i].StartPosition.Y = rand.Next(rect.Top, rect.Bottom);
                    particles[i].CurrentPosition = particles[i].StartPosition;
                    particles[i].CurrentColor = this.StartColor;
                }
                else if (particles[i].CurrentLife > particles[i].LifeTime && islooping == false)
                {
                    particles[i].IsAlive = false;
                }
            }
        }

        public void Reset(int MaxParticles)
        {
            Random rand = new Random();

            this.MaxParticles = MaxParticles;
            this.particles = new Particles[this.MaxParticles];

            for (int i = 0; i < this.MaxParticles; i++)
            {
                    particles[i] = new Particles();
                    particles[i].LifeTime = rand.Next((int)this.minLifeSpan, (int)this.maxLifeSpan);
                    particles[i].CurrentLife = 0;
                    particles[i].Scale = this.StartScale;
                    particles[i].Rotation = this.Rotation;
                    particles[i].Velocity.X = rand.Next((int)this.Velocity2.X, (int)this.Velocity1.X);
                    particles[i].Velocity.Y = rand.Next((int)this.Velocity2.Y, (int)this.Velocity1.Y);
                    particles[i].StartPosition.X = rand.Next(rect.Left, rect.Right);
                    particles[i].StartPosition.Y = rand.Next(rect.Top, rect.Bottom);
                    particles[i].CurrentPosition = particles[i].StartPosition;
                    particles[i].CurrentColor = this.StartColor;
                    particles[i].IsAlive = true;
                
            }
        }

        public void Render()
        {
            for (int i = 0; i < MaxParticles; i++)
            {
                if (particles[i].IsAlive == true)
                {
                    SGP.ManagedTextureManager.Instance.Draw(this.ImageID,
                        (int)particles[i].CurrentPosition.X,
                        (int)particles[i].CurrentPosition.Y,
                        particles[i].Scale, particles[i].Scale, Rectangle.Empty,
                        (int)(Offset.X * particles[i].Scale), (int)(Offset.Y * particles[i].Scale),
                        (int)particles[i].Rotation, particles[i].CurrentColor.ToArgb());
                }
            }
        }
    }
}
